﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using MySql.Data.MySqlClient;
using MySql.Data.Types;
using System.Collections;
using System.Text.RegularExpressions;
using System.Windows.Forms;
using mealplanner.database;

namespace mealplanner.control
{
    public class Meal
    {
        private int _meal_id;
        private string _meal_name;
        private string _meal_type;
        private string _meal_description;
        private ArrayList list = new ArrayList();
        public void setMealId(int id)
        {
            _meal_id = id;
        }
        public int getMealId()
        {
            return _meal_id;
        }
        public void setMealName(string name)
        {
            _meal_name = name;
        }
        public string getMealName()
        {
            return _meal_name;
        }
        public void setMealType(string type)
        {
            _meal_type = type;
        }
        public string getMealType()
        {
            return _meal_type;
        }
        public void setMealDescription(string description)
        {
            _meal_description = description;
        }
        public string getMealDescription()
        {
            return _meal_description;
        }

        public double checkMealName(string mealName) {
            ArrayList meals = new ArrayList();
            int flage = 0;
            if (mealName == "") {
                return 0;
            }
            meals = MealDB.getAllMealNameAndType();
            foreach (var x in meals) {
                if (mealName == x.ToString())
                {
                    flage = 1;
                    break;
                }
            }
            if (flage == 0) {
                return -1;
            }
            return 1;
        }

        public int checkType(string type) {
            switch (type)
            {
                case "Dish":
                case "Sandwich": 
                case "Soup":
                case "Juice":
                case "Salad":
                    break;
                default:
                    return 0;
            }
            return 1;
        }

        public double OveralMealCost(string MealName)
        {
            double temp=checkMealName(MealName);
            if (temp == 1)
            {
                list = MealDB.getMealCostName(MealName);
                double CostSum = 0;
                for (int i = 0; i < list.Count; i++)
                {
                    CostSum += double.Parse(list[i].ToString()) * double.Parse(list[++i].ToString());
                }
                //MessageBox.Show("COST :" + CostSum.ToString());
                return CostSum;
            }
            else {
                return temp;
            }
        }

        public double CaluclateCalories(string MealName)
        {
            double temp=checkMealName(MealName);
            if (temp == 1)
            {
                list = MealDB.getMealIngredienByMealName(MealName);
                double CalSum = 0;
                ArrayList temp_list = new ArrayList();
                for (int i = 0; i < list.Count; i++)
                {
                    temp_list = IngredientDB.getIngredientCostAndCaloriesByIngredientName(list[i].ToString());
                    CalSum += double.Parse(temp_list[1].ToString());
                }
                return CalSum;
            }
            else {
                return temp;
            }
        }

        public ArrayList MealIngredient(string MealName)
        {
            double temp=checkMealName(MealName);
            if (temp == 1)
            {
                list = MealDB.getMealIngredienByMealName(MealName);
                return list;
            }
            else
            {
                ArrayList tempList = new ArrayList();
                tempList.Add(temp);
                return tempList;
            }
        }

        /// <summary>
        /// method to return image of the meal.
        /// </summary>
        /// <param name="MealName"> name of the meal</param>
        /// <returns></returns>
        public string getImageByMealName(string MealName)
        {
            if (checkMealName(MealName) == 1)
            {
                list = MealDB.getImageByMealName(MealName);
                string image = list[0].ToString();
                return image;
            }
            else {
                return checkMealName(MealName).ToString();
            }
        }

        /// <summary>
        /// method to return meal description
        /// </summary>
        /// <param name="MealName"> name of the meal</param>
        /// <returns></returns>
        public string getDescriptionByMealName(string MealName)
        {
            if (checkMealName(MealName) == 1)
            {
                list = MealDB.getDescriptionByMealName(MealName);
                string description = list[0].ToString();
                return description;
            }
            else
            {
                return checkMealName(MealName).ToString();
            }
        }

        /// <summary>
        /// This Function categorizes meal by type ..
        /// </summary>
        /// <returns>returns the meals categorized by type </returns>
        public ArrayList ShowMeals(string type)
        {
            if (checkType(type) == 1)
            {
                //Types ..
                ArrayList Dish = new ArrayList(), Sandwich = new ArrayList();
                ArrayList Soup = new ArrayList(), Juice = new ArrayList();
                ArrayList Salad = new ArrayList();

                ArrayList sortedMeals = new ArrayList();//This array will be returned ..
                sortedMeals = MealDB.getAllMealNameAndType();
                int i;//arraylist counter
                //Custumize meal to types ..
                for (i = 1; i < sortedMeals.Count; i++)
                {
                    //whitebox testing
                    if (i != 0)
                    {

                        switch (Convert.ToString(sortedMeals[i]))
                        {
                            case "Dish":
                                Dish.Add(Convert.ToString(sortedMeals[i - 1]));
                                break;
                            case "Sandwich":
                                Sandwich.Add(Convert.ToString(sortedMeals[i - 1]));
                                break;
                            case "Soup":
                                Soup.Add(Convert.ToString(sortedMeals[i - 1]));
                                break;
                            case "Juice":
                                Juice.Add(Convert.ToString(sortedMeals[i - 1]));
                                break;
                            case "Salad":
                                Salad.Add(Convert.ToString(sortedMeals[i - 1]));
                                break;
                            default:
                                break;
                        }
                    }
                    else
                    {
                        MessageBox.Show("There is a type withou meal name .");
                    }
                }
                switch (type)
                {
                    case "Dish":
                        return Dish;
                    case "Sandwich":
                        return Sandwich;
                    case "Soup":
                        return Soup;
                    case "Juice":
                        return Juice;
                    case "Salad":
                        return Salad;
                    default:

                        break;
                }
                sortedMeals.Clear();
                return sortedMeals;
            }
            else {
                ArrayList A = new ArrayList();
                A.Add(checkType(type));
                return A;
            }
        }

        /// <summary>
        /// search the meal by name it's bridge between model and view
        /// if the name contain space like  : meet pizza the function search in db 
        /// for meet and pizza and meet pizza
        /// </summary>
        /// <param name="name"> name of the meal </param>
        /// <returns> return array list of  name meal </returns>
        public ArrayList searchMealByName(string name)
        {
            ArrayList failList = new ArrayList();
            //Regex reg = new Regex(@"^[a-zA-Z_ ]+$");
            Regex reg2 = new Regex(@"^[a-zA-Z]+$");
            Regex reg = new Regex(@"^[a-zA-Z \\&\\._]+$");
            var result2 = reg2.IsMatch(name);
            var result = reg.IsMatch(name);
            if (result == true && result2 == false)
            {
                string temp = name;
                ArrayList mealList = new ArrayList();
                string[] strArray;
                if (temp.Contains('&'))
                {
                    strArray = name.Split('&');
                    temp = string.Join(" ", strArray);
                }
                if (temp.Contains('_'))
                {
                    strArray = name.Split('_');
                    temp = string.Join(" ", strArray);
                }
                if (temp.Contains('.'))
                {
                    strArray = name.Split('.');
                    temp = string.Join(" ", strArray);
                }

                strArray = temp.Split(' ');
                foreach (string item in strArray)
                {
                    if (item != " " && item != "")
                    {
                        mealList.Add(MealDB.searchMealByMealName(removeplurals(item)));
                    }
                }
                mealList.Add(MealDB.searchMealByMealName(removeplurals(name)));
                return removeDuplicatedDataFromSearch(mealList);

            }
            else if (result2 == true && result == true)
            {
                return MealDB.searchMealByMealName(removeplurals(name));
            }
            else
            {
                failList.Add("Wrong Meal Name !");
                return failList;
            }
        }

        /// <summary>
        /// remove s from plursls words 
        /// </summary>
        /// <param name="result"> the word</param>
        /// <returns> the word with out s </returns>
        public string removeplurals(string result)
        {

            char[] temp = new char[result.Length];
            temp = result.ToCharArray();
            if (temp[temp.Length - 1] == 's' || temp[temp.Length - 1] == 'S')
            {
                char[] tempArray = new char[temp.Length - 1];
                for (int i = 0; i < tempArray.Length; i++)
                {
                    tempArray[i] = temp[i];
                }

                result = new string(tempArray);
            }
            return result;
        }

        /// <summary>
        /// remove duplicated data from array list
        /// specialy if their array list inside array list and they have duplicated data
        /// </summary>
        /// <param name="list"> array list</param>
        /// <returns> array list with out any duplicated data </returns>
        public ArrayList removeDuplicatedDataFromSearch(ArrayList list)
        {
            object[] objArray;
            ArrayList temp = new ArrayList();
            ArrayList finalList = new ArrayList();
            foreach (ArrayList item in list)
            {
                objArray = item.ToArray().Distinct().ToArray();
                for (int i = 0; i < objArray.Length; i++)
                {
                    temp.Add(objArray[i].ToString());
                }
            }

            object[] lid = temp.ToArray().Distinct().ToArray();
            for (int i = 0; i < lid.Length; i++)
            {
                finalList.Add(lid[i].ToString());
            }
            return finalList;
        }



        public string removeWhiteSpace(string item) {
            string temp = "";
            for (int i = 0; i < item.Length; i++) {
                if (item[i].ToString() != " ")
                {
                    temp = temp + item[i].ToString();
                }
                else
                {
                    break;
                }
            }

            
                return temp;
        }


        public string removeSymbols(string item) {
            string temp="";
            for (int i = 0; i < item.Length; i++)
            {
                if (item[i].ToString() != "&" && item[i].ToString() != "_")
                {
                    temp = temp + item[i].ToString();
                }
                else
                {
                    break;
                }
            }

            return temp;
        }

        /// <summary>
        /// Search for the meals that has these Ingredients
        /// </summary>
        /// <param name="ingredientsNameArray">User Specified Ingredient</param>
        /// <returns>LIst of meal names</returns>
        public ArrayList SearchMealsByIngredients(ArrayList ingredientsNameArray)
        {
            int i;
            int count;
            bool has;
            ArrayList Meals = new ArrayList();
            ArrayList IngredientsInMeal = new ArrayList();
            ArrayList checkedMeals = new ArrayList();
            string temp;
            //this for loop adds all meals in  one Meals ArrayList that ralated to all user specified ingredients. 
            for (i = 0; i < ingredientsNameArray.Count; i++)
            {
                temp = removeWhiteSpace(ingredientsNameArray[i].ToString());
                temp = removeSymbols(temp);
                ingredientsNameArray.RemoveAt(i);
                ingredientsNameArray.Insert(i, temp);
                if (ingredientsNameArray[i].ToString() == "") {
                    return Meals;
                }
                Meals.AddRange(IngredientDB.getAllMealsNameByIngredientName(removeplurals(ingredientsNameArray[i].ToString())));
            }
            Meals.Sort();
            count = Meals.Count - 1;
            while (count > 0)
            {
                //if 2 sequence meals have the same name then remove one of them.
                if (Meals[count].ToString() == Meals[count - 1].ToString())
                    Meals.RemoveAt(count);
                else
                {
                    //grantee that this meal checked once only ,in case of 2 same meals name ,one of them on checked ArrayList and another one Meals ArrayList.
                    if (checkedMeals.Contains(Meals[count].ToString()) == false)
                    {
                        //compare between 2 ArrayList Ingredients (users desired ingredients and this meal[count] ingredients) and check if all user desired Ingredients are already contained on this meal ingredients or not.
                        has = CheckMealContainsIngredients(MealDB.getMealIngredienByMealName(Meals[count].ToString()), ingredientsNameArray);
                        if (has == false)
                        {
                            // all user ingerdients don't match this meal[count] ingredients.
                            Meals.RemoveAt(count);
                        }
                        else
                        {
                            // this Array used to control count on while loop and prevents infinite loop. 
                            checkedMeals.Add(Meals[count]);
                        }

                    }
                }
                //begin where statment with new count with concerning about checkedMeal.
                count = (Meals.Count - 1) - (checkedMeals.Count);

            }
            //return Meals ArrayList after finishing while loop ,now this ArrayList Meals has distinct meals names each of them contains all user desired Ingredients. 
            return Meals;
        }

        /// <summary>
        /// checks if the meal has the all ingredients wanted by user
        /// </summary>
        /// <param name="ingInMealnames">Ingredients in the meal</param>
        /// <param name="ingUsernames">Ingredient of the user</param>
        /// <returns>true or false</returns>
        public bool CheckMealContainsIngredients(ArrayList ingInMealnames, ArrayList ingUsernames)
        {
            int i = 0;
            while (i < ingUsernames.Count)
            {
                if (ingInMealnames.Contains(ingUsernames[i].ToString()) == false)
                { return false; }

                i++;
            }
            return true;
        }

        public ArrayList getAllIngredient()
        {
            return IngredientDB.getAllIngredient();

        }

    }
}
